package com.scut.scutzone.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.scut.scutzone.entity.Comment;
import com.scut.scutzone.entity.Follow;
import com.scut.scutzone.entity.User;
import com.scut.scutzone.exception.BusinessException;


import org.jetbrains.annotations.NotNull;
import org.springframework.lang.Nullable;

import java.util.List;
import java.util.Map;

/**
 * @author: lifeng Chan
 * @date: 2021/4/28 16:00
 * @description: 定义服务层接口,具体实现类在service.impl 中实现
 * 统一错误：
 * `401`：用户未登录 (应该通过切面AOP的方式检查是否有未登录的情况)
 * `500`：服务器错误
 *
 */
public interface DatabaseService {

    /**
     * 创建用户, 如果请求不合理返还BusinessException
     * @param username
     * @param password
     * @return 创建用户成功后的uuid,和user_id
     * @throws {@link com.scut.scutzone.exception.BusinessException}
     *
     * 创建失败抛出异常，一般是
     * ErrorCode:
     * `400`：两次输入密码不一致
     *
     * `409`：用户已存在
     */
    Map.Entry<String,Integer> createUser(String username,String password) throws BusinessException;

    /**
     * 修改用户信息，除了['user_id', 'uuid', 'password', 'posts_num']外均可修改
     * @param uuid
     * @param detailKeyValueMap
     * key-blueprint:
     *     "username": "用户名",
     *     "sex": "性别 男、女、不明",
     *     "grade": "年级 数字",
     *     "major": "专业",
     *     "description": "个人介绍"
     *
     * @throws BusinessException
     * ErrorCode:
     * `400`：性别、年龄、个人介绍不符合要求
     *
     * `409`：用户名已存在
     */
    void updateUserInfo(String uuid, Map<String,Object> detailKeyValueMap) throws BusinessException;

    /**
     * 修改用户密码
     * @param uuid
     * @param old_password 旧密码
     * @param new_password 新密码
     * @throws BusinessException
     * ErrorCode:
     * `400`：两次输入密码不一致/旧密码错误
     *
     * `404`：用户不存在
     */
    void updateUserPassword(String uuid,String old_password,String new_password) throws BusinessException;

    /**
     * 用户登录
     * @param username
     * @param password
     * @return 登录成功则 返回uuid,和username,否则为空
     * @throws BusinessException
     * ErrorCode:
     * `400`：用户名或密码错误
     */
    Map.Entry<String,String> userLogin(String username,String password) throws BusinessException;

    /**
     * 通过uuid,user_id 二元对 获取用户信息
     * @param uuid
     * @param username
     * @return User 对象
     * @throws BusinessException
     * ErrorCode:
     * `404`：用户不存在
     */
    User getUser(String uuid,String username) throws BusinessException;

    /**
     * 获取用户信息的补充接口
     * @param uuid
     * @param username
     * @param searcher_uuid 查询者的uuid用来获取是否关注字段
     * @return
     * {
     *             "username": "用户名",
     *         "uuid": "uuid",
     *         "sex": "性别 男、女、不明",
     *     	"grade": "年级 数字",
     *     	"major": "专业",
     *     	"description": "个人介绍",
     *         "posts_num": "帖子数量",
     *         "avatar": "头像文件名",
     *         "bg": 背景名
     *         "fans_num": "粉丝数量",
     *         "follow_num": "关注的人的数量",
     *         "follow_status": "boolean 是否关注，只有在获取别人的信息时"
     * }
     *
     * @throws BusinessException
     */
    JSONObject getUserInfo(String uuid,String username,String searcher_uuid) throws BusinessException;

    /**
     * 查找帖子,通过给定参数，过滤出目标值
     * @param uuid 给定uuid查找法，如果不为空，则会加入此过滤条件
     * @param username 相关用户名，模糊查找 如果不为空，则会加入此过滤条件
     * @param keyword  相关关键字，精确过滤
     * @param last_id 最后一个帖子的id号，如果获取的帖子号都大于该值则查找为空,-1为不限制
     * @param limit 返回的数量限制
     * @return null 如果不满足查找条件， notnull
     * [
     *             {
     * 	            "post_id": "帖子id",
     * 	            "username": "发帖人用户名",
     * 	            "content": "内容",
     * 	            "comments_num": "评论数目",
     * 	            "comments": [
     *                    {
     * 	                    "comment_id": "评论id",
     * 	                    "parent_id": "被评论的帖子或评论的id",
     * 	                    "type": "是什么的评论，0是帖子，1是评论",
     * 	                    "content": "评论内容",
     * 	                    "comments_num": "评论数目",
     * 	                    "username": "发帖人用户名",
     *                    }
     * 	            ]
     *            },
     * ]
     */
    JSONArray getPosts(@Nullable String uuid, @Nullable String username, @Nullable String keyword, @Nullable int last_id, @NotNull int limit);

    /**
     * 通过帖子id获取帖子以及帖子下对应的评论
     * @param postId 帖子id
     * @param last_comment_id 最后一个评论的id,如果帖子下的评论id都大于该id,则帖子对应的评论列表为空null，该值-1为不限制
     * @param limit
     * @return <帖子，评论列表>键值对, 查询失败则为空
     *  {
     * 	    "post_id": "帖子id",
     * 	    "username": "发帖人用户名",
     * 	    "content": "内容",
     * 	    "imgs_name":[]
     * 	    "comments_num": "评论数目",
     * 	    "comments": [
     *                        {
     * 	            "id": "评论id",
     * 	            "parent_id": "被评论的帖子或评论的id",
     * 	            "type": "是什么的评论，0是帖子，1是评论",
     * 	            "content": "评论内容",
     * 	            "comments_num": "评论数目",
     * 	            "username": "发帖人用户名",
     *              "img_name": 评论图片
     *            }
     * 	      ]
     * 	}
     */
    JSONObject getPost(int postId, int last_comment_id, int limit);

    /**
     * 通过uuid保存帖子信息
     * @param uuid 发贴用户的uuid
     * @param content  帖子内容
     * @param imgs_name 图片名字数组
     * @return 成功则返回帖子id号，不成功则为-1
     * @throws BusinessException
     * ErrorCode:
     * `400`：帖子内容为空或长度超过120字
     *
     * `404`：当前登录用户不存在
     */
    int savePost(String uuid,String content,String[] imgs_name) throws BusinessException;

    /**
     * 更新帖子内容
     * @param post_id 帖子id,如果帖子id不存在，则会抛出业务异常
     * @param uuid uuid 提供uuid用于后台验证
     * @param content 新内容
     * @param imgs_name 新图片名字数组
     * @return 帖子id
     * @throws BusinessException
     * 异常：
     * 1.帖子对应用户的uuid与参数uuid不一致 对应403
     * 2.不存在该帖子id ，对应404
     * 3.长度限制
     *
     * ErrorCode:
     * `400`：帖子内容为空或长度超过120字
     *
     * `403`：没有权限修改该帖子
     *
     * `404`：帖子不存在
     */
    int updatePost(int post_id,String uuid,String content,String[] imgs_name) throws BusinessException;

    /**
     * 删除帖子
     * @param post_id 需要删除的帖子id号
     * @param uuid 用于验证会话的uuid号
     * @throws BusinessException 如果uuid与帖子对应用户的uuid不满足或者不存在该帖子，则会抛出业务异常
     * ErrorCode:
     * `403`：没有权限删除该帖子
     *
     * `404`：帖子不存在
     */
    void deletePost(int post_id,String uuid) throws BusinessException;

    /**
     * 通过一条评论id,获取在limit范围下的评论实体，以及对应该评论下的评论列表
     * @param commentId
     * @param limit 数量限制
     * @return
     * {
     * 		"comment_id": "评论id",
     * 		"parent_id": "被评论的帖子或评论的id",
     * 		"type": "是什么的评论，0是帖子，1是评论",
     * 		"content": "评论内容",
     * 		"comments_num": "评论数目",
     * 		"username": "发帖人用户名",
     *
     * 		"comments": [
     *                        {
     * 		        "id": "评论id",
     * 		        "parent_id": "被评论的帖子或评论的id",
     * 		        "type": "是什么的评论，0是帖子，1是评论",
     * 		        "content": "评论内容",
     * 		        "comments_num": "评论数目",
     * 		        "username": "发帖人用户名",
     *
     *            }
     * 		]
     * 	}
     * @throws BusinessException 无法检索到该评论时抛出业务异常
     * ErrorCode:
     * `404`：评论不存在
     */
    JSONObject getCommentById(int commentId,int last_comment_id, int limit) throws BusinessException;

    /**
     * 获取某个帖子下的评论，或者评论下的评论
     * @param target_id 被评论的对象id
     * @param type 是什么的评论，0是帖子，1是评论
     * @param limit 限制数目
     * @return 评论列表，如果目标没有评论，则为null
     * {
     * 	    "comments": [
     *                        {
     * 	            "comment_id": "评论id",
     * 	            "parent_id": "被评论的帖子或评论的id",
     * 	            "type": "是什么的评论，0是帖子，1是评论",
     * 	            "content": "评论内容",
     * 	            "comments_num": "评论数目",
     * 	            "username": "发帖人用户名",
     *
     *            }
     * 	      ]
     * 	}
     * @throws BusinessException 如果目标不存在，则抛出异常，
     * @comment 看了下api文档，好像这里web层接受到该异常后不需要抛出异常，直接在响应体置空“data"
     * ErrorCode:
     * `404`：目标不存在
     */
    JSONObject getComments(int target_id,int type,int last_comment_id,int limit) throws BusinessException;

    /**
     * 保存评论
     * @param target_id 评论目标id
     * @param target_type 目标类型，0是帖子，1是评论
     * @param uuid 用户uuid
     * @param content 评论内容
     * @param img_name 评论图片
     * @return 评论的id
     * @throws BusinessException 如果目标id或者uuid不存在
     * ErrorCode
     * `404`：用户/评论/帖子不存在
     */
    int saveComment(int target_id,int target_type,String uuid,String content,String img_name) throws BusinessException;

    /**
     * 更新评论
     * @param commentId 评论id
     * @param uuid 用户uuid
     * @param content 新内容
     * @param img_name 图片名字 null表示不更新，空串表示删除
     * @throws BusinessException
     * 1. 如果commentId不存在 或者
     * 2. uuid不存在 或者
     * 3. 评论所对应的用户uuid不是参数提供的uuid
     *
     * ErrorCode:
     * `400`：帖子内容为空或长度超过120字
     *
     * `403`：没有权限修改评论
     *
     * `404`：评论不存在
     */
    void updateComment(int commentId,String uuid,String content,String img_name) throws BusinessException;

    /**
     * 删除评论
     * @param commentId
     * @param uuid
     * @throws BusinessException
     * 1. 如果commentId不存在 或者
     * 2. uuid不存在 或者
     * 3. 评论所对应的用户uuid不是参数提供的uuid
     *
     * ErrorCode:
     * `403`：没有权限删除评论
     *
     * `404`：评论不存在
     */
    void deleteComment(int commentId,String uuid) throws BusinessException;

    /**
     * 搜索用户
     * @param keyword 模糊关键字
     * @param limit
     * @return 没有匹配结果则为null
     *  [
     *                {
     * 	        "username": "用户名",
     * 	        "user_id":用户id
     * 	        "sex": "性别 男、女、不明",
     * 	        "grade": "年级 数字",
     * 	        "major": "专业",
     * 	        "description": "个人介绍",
     * 	        "posts_num": "帖子数量",
     * 	        "avatar": "头像文件名"
     *        },
     * 	    ...
     * 	]
     */
    JSONArray searchUsers(String uuid,String keyword,int limit);

    /**
     * 更新头像图片名称
     * @param uuid
     * @param img_name
     * @throws BusinessException uuid不存在
     * @Comment  api 文档中有该错误 {`400`：上传失败/不支持的文件类型 }
     * ErrorCode:
     * `404`: 用户不存在
     */
    void updateAvatar(String uuid,String img_name) throws BusinessException;

    /**
     *
     * @param uuid
     * @param bg_img_name
     * @throws BusinessException uuid不存在
     * @Comment  api 文档中有该错误 {`400`：上传失败/不支持的文件类型 }
     * 检查文件类型在处理文件的模块中完成，这里不抛出此异常
     * ErrorCode:
     * `404`:用户不存在
     *
     */
    void updateBackgroundImageName(String uuid,String bg_img_name) throws BusinessException;

    /**
     * 关注或者取关用户
     * @param uuid 进行关注或者取关操作的用户uuid
     * @param username 关注或者取关的对象
     * @param status 0为取关，1为关注
     * @throws BusinessException
     * 抛出异常：对应404
     * 1. uuid不存在
     * 2. username不存在
     *
     * ErrorCode:
     * `400`：未关注/已关注该用户
     *
     * `404`：用户不存在
     */
    void followUser(String uuid,String username,int status) throws BusinessException;

    /**
     * 获取关注列表
     * @param user_id
     * @param limit
     * @return 通过关注列表返回Follow实体类列表
     * @throws BusinessException user_id不存在
     * ErrorCode:
     * `404`：用户不存在
     */
    @Deprecated
    List<Follow> getFollowList(int user_id,int limit) throws BusinessException;

    /**
     * 该方法更适用于业务场景使用，获取一个json数组格式的关注列表
     * @param username 要获取关注列表的用户名字
     * @param limit
     * @return
     *
     *     [{
     *         follow_id:int
     *         user_id:int
     *         user_username:String
     *         user_avatar:String
     *         user_description:String
     *         followed_user_id:int
     *         followed_username: String
     *         followed_user_description: String
     *         followed_user_avatar: String
     *         status:int
     *     }
     *     ...
     *     ]
     *
     * @throws BusinessException user_id 不存在
     * ErrorCode:
     * `404`：用户不存在
     */
    JSONArray getFollowJSONArray(String username,int limit) throws BusinessException;

    /**
     * 获取给定user_id的粉丝列表
     * @param user_id
     * @param limit
     * @return Follow实体类列表
     * @throws BusinessException
     * ErrorCode:
     * `404`：用户不存在
     */
    @Deprecated
    List<Follow> getFansList(int user_id,int limit) throws BusinessException;

    /**
     * 获取粉丝列表
     * @param username
     * @param limit
     * @return
     * 获取值时，先获取对应索引位的jsonObject再根据下面的键值查找值
     *     [{
     *         follow_id:int
     *         user_id:int
     *         user_username:String
     *         user_avatar:String
     *         user_description:String
     *         followed_user_id:int
     *         followed_username: String
     *         followed_user_description: String
     *         followed_user_avatar: String
     *         status:int
     *     }
     *     ...
     *     ]
     * @throws BusinessException user_id不存在
     * ErrorCode:
     * `404`：用户不存在
     */
    JSONArray getFansJSONArray(String username,int limit) throws BusinessException;



}
